using namespace std;

#include <iostream>
#include <atomic>

template<typename T>
class SharedPtr;

template<typename T>
class WeakPtr;

// 控制块，用于管理引用计数
struct ControlBlock 
{
    ControlBlock()
        : shared_count(1)
        , weak_count(0)
    {

    }

    std::atomic<int> shared_count;
    std::atomic<int> weak_count;
};

// SharedPtr 类
template<typename T>
class SharedPtr
{
    // 友元类 WeakPtr 可以访问 SharedPtr 的私有成员
    friend class WeakPtr<T>;


private:
    T* _ptr;
    ControlBlock* _control_block;
    std::function<void(T*)> _deleter = [](https://gitcode.com/LHRan_ran_/smart_ptr/tree/undefined/T* ptr) { delete ptr; };

    void release()
    {
        if (_control_block)
        {
            if (--_control_block->shared_count == 0)
            {
                // delete _ptr;
                _deleter(_ptr);
                if (_control_block->weak_count == 0)
                {
                    delete _control_block;
                    _deleter = std::function<void(T*)>();
                }
            }
        }
    }
   
public:
    // 构造函数
    SharedPtr(T* ptr = nullptr)
        : _ptr(ptr)
    {
        if (_ptr)
            _control_block = new ControlBlock();
        else
            _control_block = nullptr;
    }

    // 带删除器的构造函数
    template<class D>
    SharedPtr(T* ptr, D deleter)
        : _ptr(ptr)
        , _deleter(deleter)
    {
        if (_ptr)
            _control_block = new ControlBlock();
        else
            _control_block = nullptr;
    }

    // 从“const WeakPtr<T>”转换为“SharedPtr<int>”
    SharedPtr(const WeakPtr<T>& other)
    {
        _ptr = other._ptr;
        _control_block = other._control_block;

        if (_control_block)
            ++_control_block->shared_count;
    }

    // 拷贝构造函数
    SharedPtr(const SharedPtr& other)
    {
        _ptr = other._ptr;
        _control_block = other._control_block;
        _deleter = other._deleter;

        if (_control_block)
            ++_control_block->shared_count;
    }

    // 移动构造函数
    SharedPtr(SharedPtr&& other) noexcept
        : _ptr(other._ptr)
        , _control_block(other._control_block)
        ,_deleter(std::move(other._deleter))
    {
        other._ptr = nullptr;
        other._control_block = nullptr;
        other._deleter = std::function<void(T*)>();
    }

    // 赋值重载
    SharedPtr& operator=(const SharedPtr& other)
    {
        if (this != &other)
        {
            release();

            _ptr = other._ptr;
            _control_block = other._control_block;
            _deleter = other._deleter;

            if (_control_block)
                ++_control_block->shared_count;
        }
        return *this;
    }

    // 移动赋值
    SharedPtr& operator=(SharedPtr&& other) noexcept
    {
        if (this != &other)
        {
            release();

            _ptr = other._ptr;
            _control_block = other._control_block;
            _deleter = std::move(other._deleter);

            other._ptr = nullptr;
            other._control_block = nullptr;
            other._deleter = std::function<void(T*)>();
        }
        return *this;

    }

    // 析构函数
    ~SharedPtr()
    {
        release();
    }

    // 获取底层指针
    T* get() const
    {
        return _ptr;
    }

    // 获取引用计数
    std::atomic<int> use_count() const
    {
        return _control_block ? _control_block->shared_count.load() : 0;
    }

    // 获取weak_count
    std::atomic<int> weak_count() const
    {
        return _control_block ? _control_block->weak_count.load() : 0;
    }

    // 重载 -> 和 * 操作符
    T* operator->() const
    {
        return _ptr;
    }

    T& operator*() const
    {
        return *_ptr;
    }

    // reset
    void reset(T* ptr = nullptr)
    {
        if (ptr != _ptr)
        {
            release();

            _ptr = ptr;
            if (_ptr)
                _control_block = new ControlBlock();
            else
                _control_block = nullptr;
        }
    }

};


// WeakPtr 类
template<typename T>
class WeakPtr
{
    // 友元类
    friend class SharedPtr<T>;

private:
    T* _ptr;
    ControlBlock* _control_block;

    void release()
    {
        if (_control_block)
        {
            if (--_control_block->weak_count == 0 && _control_block->shared_count == 0)
                delete _control_block;
        }
    }
public:
    // 默认构造函数
    WeakPtr()
        : _ptr(nullptr)
        , _control_block(nullptr)
    {

    }

    // WeakPtr拷贝构造函数
    WeakPtr(const WeakPtr& other)
    {
        _ptr = other._ptr;
        _control_block = other._control_block;

        if (_control_block)
            ++_control_block->weak_count;
    }

    // WeakPtr赋值运算符
    WeakPtr& operator=(const WeakPtr& other)
    {
        if (this != &other)
        {
            release();

            _ptr = other._ptr;
            _control_block = other._control_block;

            if (_control_block)
                ++_control_block->weak_count;
        }
        return *this;
    }

    // 由 SharedPtr 构造 WeakPtr
    WeakPtr(const SharedPtr<T>& shared_ptr)
    {
        cout << "WeakPtr(const SharedPtr<T>& shared_ptr)" << endl;

        _ptr = shared_ptr._ptr;
        _control_block = shared_ptr._control_block;

        if (_control_block)
            ++_control_block->weak_count;
    }

    // 由 SharedPtr 赋值给 WeakPtr
    WeakPtr& operator=(const SharedPtr<T>& shared_ptr)
    {
        cout << "WeakPtr& operator=(const SharedPtr<T>& shared_ptr)" << endl;

        if (this != &shared_ptr)
        {
            release();
        }
        _ptr = shared_ptr._ptr;
        _control_block = shared_ptr._control_block;
        if (_control_block)
            ++_control_block->weak_count;

        return *this;
    }

    // 析构函数
    ~WeakPtr()
    {
        release();
    }

    // 实现expired()函数
    bool expired() const
    {
        return !_control_block || _control_block->shared_count == 0;
    }


    // 从 WeakPtr 锁定为 SharedPtr
    SharedPtr<T> lock() const
    {
        if (!expired())
            return SharedPtr<T>(*this);
        else
            return SharedPtr<T>(nullptr);
    }

    // 实现use_count
    int use_count() const
    {
        return _control_block ? _control_block->shared_count.load() : 0;
    }

    // 获取weak_count
    int weak_count() const
    {
        return _control_block ? _control_block->weak_count.load() : 0;
    }

    // reset 方法：重置当前 WeakPtr
    void reset()
    {
        release();

        _ptr = nullptr; // 置空指针
        _control_block = nullptr; // 置空控制块
    }
};

template <typename T>
void WeakPtrShowCount(WeakPtr<T>& wp)
{
    cout << "shared_count: " << wp.use_count() << endl;
    cout << "weak_count: " << wp.weak_count() << endl;
}

template <typename T>
void SharedPtrShowCount(SharedPtr<T>& sp)
{
    cout << "shared_count: " << sp.use_count() << endl;
    cout << "weak_count: " << sp.weak_count() << endl;
}

void testMYSmartPointer()
{
    SharedPtr<int> sp(new int(10));
    SharedPtrShowCount(sp);

    WeakPtr<int> wp(sp);
    SharedPtrShowCount(sp);
    WeakPtrShowCount(wp);

    {
        SharedPtr<int> sp2 = wp.lock();
        SharedPtrShowCount(sp);
        WeakPtrShowCount(wp);
        SharedPtrShowCount(sp2);
    }
}
template <class T>
struct DeleteArray
{
    void operator()(T* ptr)
    {
       delete[] ptr;
    }
};
void testDeleter()
{
    struct Date
    {
        int _year = 0;
        int _month = 0;
        int _day = 0;

        // 实现析构函数会报错！
        ~Date()
        {
            cout << "~Date()" << endl;
        }
    };
    

    SharedPtr<int> sp0(new int[10]);
    SharedPtr<int> sp1(new int[10], [](https://gitcode.com/LHRan_ran_/smart_ptr/tree/undefined/int* ptr) { delete[] ptr; });
    //SharedPtr<Date> sp2(new Date[10]); // error
    SharedPtr<Date> sp3(new Date[10], [](https://gitcode.com/LHRan_ran_/smart_ptr/tree/undefined/Date* ptr) {delete[] ptr; });
    SharedPtr<Date> sp4(new Date[10], DeleteArray<Date>());
    SharedPtr<FILE> sp5(fopen("./main.cpp", "r"), [](https://gitcode.com/LHRan_ran_/smart_ptr/tree/undefined/FILE* fp) {fclose(fp); });

    auto deleter = [](https://gitcode.com/LHRan_ran_/smart_ptr/tree/undefined/Date* ptr){ delete[] ptr; };
    SharedPtr<Date> sp(new Date[10], deleter);

}

// 测试代码
int main()
{
    //testMYSmartPointer();

    testDeleter();

    return 0;
}
